DPDK中的多线程模型

您所在的位置:网站首页 hugepagesize相关配置linux dpdk DPDK中的多线程模型

DPDK中的多线程模型

2023-03-16 15:32| 来源: 网络整理| 查看: 265

最近在做dpdk相关的开发和调优,有点小压力,但还是能成长的,打算用两篇博客来介绍下dpdk中的多线程模型,然后下一篇介绍它里面的一些优化方法和NUMA架构[高性能的原因]。 主要是截取相关的源代码进行分析,以及开发过程中可能会遇到的一些坑[一些点参考书《深入dpdk》]。

这里每个线程运行在一个核上,在启动时就绑定了,防止上下文切换等性能开销。从helloworld例子开始吧〜

比如启动参数为-c 0xff,在main入口处,会调用rte_eal_init初始化运行相关的参数,其中对启动线程相关的参数分析eal_parse_coremask,主要实现如下:

274 static int 275 eal_parse_coremask(const char *coremask) 276 { 277 struct rte_config *cfg = rte_eal_get_configuration(); 278 int i, j, idx = 0; 279 unsigned count = 0; 280 char c; 281 int val; 282 283 if (coremask == NULL) 284 return -1; 285 /* Remove all blank characters ahead and after . 286 * Remove 0x/0X if exists. 287 */ 288 while (isblank(*coremask)) 289 coremask++; 290 if (coremask[0] == '0' && ((coremask[1] == 'x') 291 || (coremask[1] == 'X'))) 292 coremask += 2; 293 i = strlen(coremask); 294 while ((i > 0) && isblank(coremask[i - 1])) 295 i--; 296 if (i == 0) 297 return -1; 299 for (i = i - 1; i >= 0 && idx lcore_role[idx] = ROLE_RTE; 315 lcore_config[idx].core_index = count; 316 count++; 317 } else { 318 cfg->lcore_role[idx] = ROLE_OFF; 319 lcore_config[idx].core_index = -1; 320 } 321 } 322 } 323 for (; i >= 0; i--) 324 if (coremask[i] != '0') 325 return -1; 326 for (; idx lcore_role[idx] = ROLE_OFF; 328 lcore_config[idx].core_index = -1; 329 } 330 if (count == 0) 331 return -1; 332 /* Update the count of enabled logical cores of the EAL configuration */ 333 cfg->lcore_count = count; 334 return 0; 335 } ​ 79 struct rte_config { 80 uint32_t master_lcore; /**< Id of the master lcore */ 81 uint32_t lcore_count; /**< Number of available logical cores. */ 82 enum rte_lcore_role_t lcore_role[RTE_MAX_LCORE]; /**< State of cores. */ 83 84 /** Primary or secondary configuration */ 85 enum rte_proc_type_t process_type; 86 87 /** 88 * Pointer to memory configuration, which may be shared across multiple 89 * DPDK instances 90 */ 91 struct rte_mem_config *mem_config; 92 } __attribute__((__packed__)); ​ 63 struct lcore_config { 64 unsigned detected; /**< true if lcore was detected */ 65 pthread_t thread_id; /**< pthread identifier */ 66 int pipe_master2slave[2]; /**< communication pipe with master */ 67 int pipe_slave2master[2]; /**< communication pipe with master */ 68 lcore_function_t * volatile f; /**< function to call */ 69 void * volatile arg; /**< argument of function */ 70 volatile int ret; /**< return value of function */ 71 volatile enum rte_lcore_state_t state; /**< lcore state */ 72 unsigned socket_id; /**< physical socket id for this lcore */ 73 unsigned core_id; /**< core number on socket for this lcore */ 74 int core_index; /**< relative index, starting from 0 */ 75 rte_cpuset_t cpuset; /**< cpu set which the lcore affinity to */ 76 };

行288~297是跳过启动参数-c 0xff中-c和0xff之间的空白符,跳过0x,并跳过ff右边的空白符,即执行完此语句后只剩下ff; 行299~322是对ff从右往左依次判断是否是十六进制数字,然后再转换成int型,比如f对应的int的二进制为000...1111,如果相应的位为1则执行cfg->lcore_role[idx] = ROLE_RTE[在core_config[idx].detected为true的情况下],否则cfg->lcore_role[idx] = ROLE_OFF; 行323~334分别对其它位置的参数检测,因为RTE_MAX_LCORE在此源码中为32,跳出行299的循环要么是return -1,要么是idx < RTE_MAX_LCORE,如果输入的参数比如0x444ffffff是有问题的,再如0x00000000ffffff则合法,并对未设置的核进行cfg->lcore_role[idx] = ROLE_OFF; struct lcore_config是核的配置结构数据,而struct rte_config是全局rte配置结构数据;

53 int 54 rte_eal_cpu_init(void) 55 { 56 /* pointer to global configuration */ 57 struct rte_config *config = rte_eal_get_configuration(); 58 unsigned lcore_id; 59 unsigned count = 0; 60 61 /* 62 * Parse the maximum set of logical cores, detect the subset of running 63 * ones and enable them by default. 64 */ 65 for (lcore_id = 0; lcore_id lcore_role[lcore_id] = ROLE_OFF; 75 lcore_config[lcore_id].core_index = -1; 76 continue; 77 } 78 79 /* By default, lcore 1:1 map to cpu id */ 80 CPU_SET(lcore_id, &lcore_config[lcore_id].cpuset); 81 82 /* By default, each detected core is enabled */ 83 config->lcore_role[lcore_id] = ROLE_RTE; 84 lcore_config[lcore_id].core_id = eal_cpu_core_id(lcore_id); 85 lcore_config[lcore_id].socket_id = eal_cpu_socket_id(lcore_id); 100 count++; 101 } 102 /* Set the count of enabled logical cores of the EAL configuration */ 103 config->lcore_count = count; 108 //more code... 109 return 0; 110 }

rte_eal_cpu_init函数主要设置每个线程lcore_config相关信息,其中CPU_ZERO和CPU_SET是设置相关cpu亲和性的接口,这里指的是硬亲和性;简单解释下这样做的好处:使得线/进程在某个给定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,迁移的频率小就意味着产生的负载小,提高了cpu cache的命中率,从而减少内存访问损耗,提高程序的速度,每个核心可以更专注地处理一件事情,资源体系被充分使用,减少了同步的损耗;

99 /* set affinity for current thread */ 100 static int 101 eal_thread_set_affinity(void) 102 { 103 unsigned lcore_id = rte_lcore_id(); 104 105 /* acquire system unique id */ 106 rte_gettid(); 107 108 /* update EAL thread core affinity */ 109 return rte_thread_set_affinity(&lcore_config[lcore_id].cpuset); 110 } 112 void eal_thread_init_master(unsigned lcore_id) 113 { 114 /* set the lcore ID in per-lcore memory area */ 115 RTE_PER_LCORE(_lcore_id) = lcore_id; 116 117 /* set CPU affinity */ 118 if (eal_thread_set_affinity()



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3